package ca.seia.comp6521.a2.itemsetstorage;

import gnu.trove.iterator.TObjectIntIterator;
import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import ca.seia.comp6521.a2.io.DataFileWriter;

public class CharTriples implements PairStorage{

private TObjectIntMap<CharPair> countMap;
	
	private int count;

	public CharTriples() {
		this.countMap = new TObjectIntHashMap<CharPair>();
		
	}

	@Override
	public void addCount(int value1, int value2) {
		this.countMap.adjustOrPutValue(new CharPair(value1, value2), 1, 1);
		count++;
		//System.out.println("Size of free memory " + MemoryUtil.free());
		if (this.countMap.size() == 102877) {
			System.out.println("reached max flushing content");
			this.countMap = null;
			this.countMap = new TObjectIntHashMap<CharPair>();
			System.out.println(count);
		}
	}

	@Override
	public int getPairCount(int value1, int value2) {
		return this.countMap.get(new CharPair(value1,value2));
	}
	
	public void removeInfrequentPairs(int support) {
		for (Object pair :this.countMap.keys() ) {
			if(this.countMap.get(pair) < support) {
				this.countMap.remove(pair);
			}
		}
	}
	
	public void removeInfrequentPairsAndWriteToDisk(int support, DataFileWriter fileWriter) throws IOException {

		for (TObjectIntIterator iterator = countMap.iterator(); iterator.hasNext();) {
			iterator.advance();
			if ( iterator.value() >=  support) {
				fileWriter.writeItems((ExternilizableItems) iterator.key(), iterator.value());
			} else {
				iterator.remove();
			}
		}
	}
	
	public void writeToDisk(int support, DataFileWriter fileWriter) throws IOException {
		
		TObjectIntIterator iterator = countMap.iterator();
		int mapSize = countMap.size();
		for (int i = mapSize; i-- > 0;) {
			iterator.advance();
			fileWriter.writeItems((ExternilizableItems) iterator.key(), iterator.value());
		}
		fileWriter.close();
	}
	
	public List<CharItems> generateCandidateTriplets() {
		CharPair[] keys = (CharPair[]) this.countMap.keys(new CharPair[0]);
		
		Arrays.sort(keys);
		List<CharItems> triplets = new ArrayList<CharItems>();
		
		int keyLength = keys.length;
		for(int keyIndex = 0 ; keyIndex < keyLength ; keyIndex++) {
			for(int secondPairIndex = keyIndex + 1; secondPairIndex < keyLength ; secondPairIndex++) {
				CharItems triplet = CharItems.generateCandidateTriplet(keys[keyIndex], keys[secondPairIndex]);
				if(triplet == null) {
					break;
				} else {
					triplets.add(triplet);
				}
			}
		}
		return triplets;
	}
	
	@Override
	public String toString() {
		return this.countMap.toString() + " count of pairs is = " + this.countMap.size();
	}

}
